package com.tanhua.manage.service;

import cn.hutool.crypto.digest.DigestUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tanhua.domain.db.User;
import com.tanhua.manage.domain.Admin;
import com.tanhua.manage.exception.BusinessException;
import com.tanhua.manage.mapper.AdminMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.cli.Digest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Service
public class AdminService extends ServiceImpl<AdminMapper,Admin>{

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired(required = false)
    private AdminMapper adminMapper;

    private static final String MANAGE_CAP ="MANAGE_CAP_";

    private static final String MANAGE_TOKEN ="MANAGE_TOKEN_";

    @Value("tanhua.secret")
    private String secret;

    //把验证码保存到redis中
    public void saveCap(String uuid, String code) {
        String key = MANAGE_CAP+uuid;
        redisTemplate.opsForValue().set(key,code, Duration.ofMinutes(5)); //五分钟失效，实际工作中一般是一分钟或者30秒
    }

    /**
     * 登陆的方法
     * @param paramMap
     * @return
     */
    public ResponseEntity login(Map<String, String> paramMap) {
//        1.获取请求参数
        String username = paramMap.get("username");
        String password = paramMap.get("password");
        String verificationCode = paramMap.get("verificationCode");
        String uuid = paramMap.get("uuid");
//        2.判断用户名密码是否为空
        if(StringUtils.isEmpty(username)||StringUtils.isEmpty(password)){
            throw  new BusinessException("用户名与密码不能为空"); //异常类一般都是见名知意，
        }
//        2.1 判断用户名是否存在
        Admin admin = query().eq("username", username).one();
        if(admin==null){
            throw  new BusinessException("用户名不存在");
        }
//        2.2 判断密码是否正确
        if(!admin.getPassword().equals(DigestUtil.md5Hex(password))){
            throw  new BusinessException("密码错误");
        }
//        3.判断验证码
//        3.1 验证码参数非空判断
        if(StringUtils.isEmpty(verificationCode)){
            throw  new BusinessException("验证码不能为空");
        }
//        3.2 校验验证码
        //取出redis的验证码
        String key = MANAGE_CAP+uuid;
        String authCode = redisTemplate.opsForValue().get(key);
        if(!verificationCode.equalsIgnoreCase(authCode)){
            throw  new BusinessException("验证码错误");
        }
//        4.删除验证码
        redisTemplate.delete(key);
//        5.生成token
        Map<String,Object> claimsMap = new HashMap<>();
        claimsMap.put("id",admin.getId());
        claimsMap.put("username",admin.getUsername());
        String token = Jwts.builder().setClaims(claimsMap).signWith(SignatureAlgorithm.HS256, secret).compact();
//        6.用户对象存入redis
        String adminJson = JSON.toJSONString(admin);
        String tokenKey = MANAGE_TOKEN+token;
        redisTemplate.opsForValue().set(tokenKey,adminJson,Duration.ofHours(4)); //默认4小时销毁
//        7.返回结果
        Map<String,String> resultMap = new HashMap<>();
        resultMap.put("token",token);
        return ResponseEntity.ok(resultMap);
    }



    //根据Token查找Admin对象
    public Admin findAdminByToken(String token) {
        String tokenKey = MANAGE_TOKEN+token;
        String adminJson = redisTemplate.opsForValue().get(tokenKey);
        if(adminJson==null){
            //这个token查找不到登录用户
            return null;
        }
        Admin admin = JSON.parseObject(adminJson, Admin.class);
        return admin;
    }

    //退出登陆
    public ResponseEntity logout(String token) {
        String tokenKey = MANAGE_TOKEN+token;
        redisTemplate.delete(tokenKey);
        return ResponseEntity.ok(null);
    }
}
